
package com.idealighter.game.personalcenter.manager;

import com.google.inject.Inject;
import com.google.inject.Singleton;

import com.idealighter.game.common.CommonMsgMgr;
import com.idealighter.game.common.SmsMgr;
import com.idealighter.game.core.assertions.HuohuaAssert;
import com.idealighter.game.core.constant.Operator;
import com.idealighter.game.core.error.ErrorCode;
import com.idealighter.game.core.util.PwdEncode;
import com.idealighter.game.core.util.RandomKeyGenerator;
import com.idealighter.game.dblog.service.DbLogService;
import com.idealighter.game.dictionary.dic.PlayerHeadSrcDic;
import com.idealighter.game.log.struct.personalcenter.BindPhoneLog;
import com.idealighter.game.log.struct.personalcenter.ModifyBankPwdLog;
import com.idealighter.game.log.struct.personalcenter.ModifyLoginPwdLog;
import com.idealighter.game.log.struct.personalcenter.ModifyPwdProtectLog;
import com.idealighter.game.log.struct.personalcenter.RealNameAuthenticateLog;
import com.idealighter.game.login.manager.LoginMgr;
import com.idealighter.game.message.core.ResMessage;
import com.idealighter.game.personalcenter.dto.PlayerBaseInfo;
import com.idealighter.game.player.manager.PlayerMgr;
import com.idealighter.game.player.service.bo.PlayerBo;
import com.idealighter.game.player.struct.Player;
import com.idealighter.utils.check.CheckUtil;
import com.idealighter.utils.check.EmptyUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 个人中心管理 .
 * 
 * @date 2015年11月11日 下午7:52:22
 *
 */
@Singleton
public class PersonalCenterMgr {

  private static final Logger LOG = LoggerFactory.getLogger(PersonalCenterMgr.class);

  public static final String EMAIL_REGEX =
      "^\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+$";
  public static final String NAME_PATTERN = "^[\\u4E00-\\u9FA5]{2,15}$";
  public static final String IDNO_PATTERN = "(\\d{14}[0-9a-zA-Z])|(\\d{17}[0-9a-zA-Z])";

  // 签名最大长度
  // private static final int SIGNATURE_MAX_LENGTH = 50;
  // 刷新手机登录验证码间隔时间(毫秒)
  private static final int REFRESH_BIND_PHONE_KEY_INTERVAL = 60000;

  @Inject
  private CommonMsgMgr commonMsgMgr;
  @Inject
  private PersonalCenterMsgMgr msgMgr;
  @Inject
  private PlayerHeadSrcDic playerIconDic;
  @Inject
  private SmsMgr smsMgr;
  @Inject
  private PlayerMgr playerMgr;
  @Inject
  private LoginMgr loginMgr;

  /**
   * 进入个人中心 .
   * 
   * @param player 玩家.
   * @param bankPwd .
   */
  public ResMessage enterPersonalCenter(Player player, String bankPwd) {
    if (!player.getBankPwd().equals(PwdEncode.encodeWithTail(bankPwd))) {
      LOG.warn("玩家[{}][{}]进入个人中心银行密码不正确", player.getPlayerName(), player.getId());
      return msgMgr.sendEnterPersonalCenterMsg(1);
    }

    // LOG.info("玩家[{}][{}]进入个人中心成功", player.getPlayerName(), player.getId());
    return msgMgr.sendEnterPersonalCenterMsg(0);
  }

  /**
   * 修改玩家基本信息 .
   * 
   * @param player 玩家.
   * @param baseInfo .
   */
  public ResMessage modifyBaseInfo(Player player, PlayerBaseInfo baseInfo) {
    if (!playerIconDic.getIcons().contains(baseInfo.getIcon())) {
      LOG.error("玩家[{}][{}]修改使用的图标[{}]不存在", player.getPlayerName(), player.getId(),
          baseInfo.getIcon());
      // commonMsgMgr.sendErrorDlgMsg(player, ErrorCode.BAD_REQUEST, Operator.SYSTEM);
      HuohuaAssert.isTrue(false);
    }

    HuohuaAssert.isTrue(loginMgr.checkPlayerName(player, baseInfo.getNickName()));

    player.setIcon(baseInfo.getIcon());
    player.setPlayerName(baseInfo.getNickName());


    playerMgr.asyncUpdatePlayer(player);
    LOG.info("玩家[{}][{}]修改玩家基本信息成功", player.getUserName(), player.getId());

    return msgMgr.sendModifyBaseInfoMsg(baseInfo);
  }

  /**
   * 玩家请求实名认证,不能重复认证 .
   * 
   * @param player 玩家.
   * @param name .
   * @param idNo .
   */
  public void realNameAuthenticate(Player player, String name, String idNo) {
    if (player.getIdcard() != null && player.getName() != null
        && player.getName().trim().length() != 0) {
      LOG.warn("玩家[{}][{}]已经进行过实名认证,请勿重复认证", player.getPlayerName(), player.getId());
      msgMgr.sendRealNameAuthenticateMsg(player, 1);
      return;
    }

    if (name == null || !name.matches(NAME_PATTERN)) {
      LOG.warn("玩家[{}][{}]的姓名[{}]格式不合法", player.getPlayerName(), player.getId(), name);
      msgMgr.sendRealNameAuthenticateMsg(player, 2);
      return;
    }

    if (idNo == null || !idNo.matches(IDNO_PATTERN)) {
      LOG.warn("玩家[{}][{}]的身份证号码[{}]不合法", player.getPlayerName(), player.getId(), idNo);
      msgMgr.sendRealNameAuthenticateMsg(player, 3);
      return;
    }

    player.setName(name);
    player.setIdcard(idNo);
    msgMgr.sendRealNameAuthenticateMsg(player, 0);
    playerMgr.asyncUpdatePlayer(player);
    LOG.info("玩家[{}][{}]实名认证成功", player.getUserName(), player.getId());
    DbLogService.log(new RealNameAuthenticateLog(player, name, idNo));
  }

  /**
   * 玩家修改登录密码 .
   * 
   * @param player 玩家.
   * @param oldPwd .
   * @param newPwd .
   */
  public ResMessage modifyLoginPwd(Player player, String oldPwd, String newPwd) {
    if (!PwdEncode.encodeWithTail(oldPwd).equals(player.getPassword())) {
      LOG.warn("玩家[{}][{}]输入的旧的登录密码不正确", player.getPlayerName(), player.getId());
      return msgMgr.sendModifyLoginPwdMsg(1);
    }

    if (!newPwd.matches(Player.PASSWORD_PATTERN)) {
      LOG.warn("玩家[{}][{}]输入的新的登录密码格式不合法", player.getPlayerName(), player.getId());
      return msgMgr.sendModifyLoginPwdMsg(2);
    }

    player.setPassword(PwdEncode.encodeWithTail(newPwd));

    playerMgr.asyncUpdatePlayer(player);
    LOG.info("玩家[{}][{}]修改登录密码成功", player.getUserName(), player.getId());
    DbLogService.log(new ModifyLoginPwdLog(player));

    return msgMgr.sendModifyLoginPwdMsg(0);
  }

  /**
   * 修改银行密码 .
   * 
   * @param player 玩家.
   * @param oldPwd .
   * @param newPwd .
   */
  public ResMessage modifyBankPwd(Player player, String oldPwd, String newPwd) {
    if (!PwdEncode.encodeWithTail(oldPwd).equals(player.getBankPwd())) {
      LOG.warn("玩家[{}][{}]输入的旧的银行密码不正确", player.getPlayerName(), player.getId());
      // commonMsgMgr.sendErrorDlgMsg(player, ErrorCode.BANK_PWD_ERROR, Operator.SYSTEM);
      HuohuaAssert.isTrue(false, ErrorCode.BANK_PWD_ERROR);
    }

    if (!newPwd.matches(Player.PASSWORD_PATTERN)) {
      LOG.warn("玩家[{}][{}]输入的新的银行密码格式不合法", player.getPlayerName(), player.getId());
      // commonMsgMgr.sendErrorDlgMsg(player, ErrorCode.BAD_REQUEST, Operator.SYSTEM);
      HuohuaAssert.isTrue(false);
    }

    player.setBankPwd(PwdEncode.encodeWithTail(newPwd));

    playerMgr.asyncUpdatePlayer(player);
    LOG.info("玩家[{}][{}]修改银行密码成功", player.getUserName(), player.getId());
    DbLogService.log(new ModifyBankPwdLog(player));

    return msgMgr.sendModifyBankPwdMsg(player);
  }

  /**
   * 修改密保问题 .
   * 
   * @param player 玩家.
   * @param firstPwdProtectQ .
   * @param firstPwdProtectA .
   * @param secondPwdProtectQ .
   * @param secondPwdProtectA .
   */
  public void modifyPwdProtect(Player player, String firstPwdProtectQ, String firstPwdProtectA,
      String secondPwdProtectQ, String secondPwdProtectA) {
    if (player.getFirstPwdProtectQ() != null) {
      LOG.error("玩家[{}][{}]已经设置密保不能重复设置", player.getPlayerName(), player.getId());
      return;
    }

    if (firstPwdProtectQ == null || firstPwdProtectQ.trim().equals("") || firstPwdProtectA == null
        || firstPwdProtectA.trim().equals("") || secondPwdProtectQ == null
        || secondPwdProtectQ.trim().equals("") || secondPwdProtectA == null
        || secondPwdProtectA.trim().equals("")) {
      LOG.error("玩家[{}][{}]密保输入有空不合法", player.getPlayerName(), player.getId());
      return;
    }

    player.setFirstPwdProtectQ(firstPwdProtectQ);
    player.setFirstPwdProtectA(firstPwdProtectA);
    player.setSecondPwdProtectQ(secondPwdProtectQ);
    player.setSecondPwdProtectA(secondPwdProtectA);

    playerMgr.asyncUpdatePlayer(player);
    LOG.info("玩家[{}][{}]设置密保成功", player.getUserName(), player.getId());
    msgMgr.sendModifyPwdProtectMsg(player);
    DbLogService.log(new ModifyPwdProtectLog(player));
  }

  /**
   * 获取绑定手机验证码 .
   * 
   * @param player 玩家.
   * @param phone .
   */
  public ResMessage getBindPhoneKey(Player player, String phone) {

    HuohuaAssert.isTrue(CheckUtil.checkTelephone(phone), ErrorCode.BAD_REQUEST);

    // if (phone == null) {
    // LOG.error("玩家[{}][{}]获取绑定手机验证码时没有输入手机号码", player.getPlayerName(), player.getId());
    // return;
    // }

    // if (!phone.matches("^1\\d{10}$")) {
    // msgMgr.sendGetBindPhoneKeyMsg(player, 1, 0);
    // LOG.warn("玩家[{}][{}]输入的手机号[{}]格式不正确", player.getPlayerName(), player.getId(), phone);
    // return;
    // }

    // 校验用户存在否
    PlayerBo playerBo = playerMgr.selectPlayerByPhone(phone);

    HuohuaAssert.isTrue(playerBo == null, ErrorCode.USER_ALREADY_BIND_PHONE);

    // if (palyerDomain != null) {
    // LOG.error("手机[{}]已经绑定", phone);
    // msgMgr.sendGetBindPhoneKeyMsg(player, 3, 0);
    // return;
    // }

    long now = System.currentTimeMillis();
    // 给客户端延时2秒

    HuohuaAssert.isTrue(now - player.getBindPhoneKeyTime + 2000 >= REFRESH_BIND_PHONE_KEY_INTERVAL,
        ErrorCode.SMS_FREQUENT);

    // if (now - player.getBindPhoneKeyTime + 2000 < REFRESH_BIND_PHONE_KEY_INTERVAL) {
    // LOG.warn("玩家[{}][{}]刷新绑定手机验证码低于时间间隔[{}]毫秒", player.getId(), player.getPlayerName(),
    // REFRESH_BIND_PHONE_KEY_INTERVAL);
    // msgMgr.sendGetBindPhoneKeyMsg(player, 2, (int) ((now - player.getBindPhoneKeyTime) / 1000));
    // return;
    // }

    player.tmpBindPhone = phone;
    player.bindPhoneKey = RandomKeyGenerator.generateNum(6);
    player.getBindPhoneKeyTime = now;

    playerMgr.asyncUpdatePlayer(player);
    smsMgr.sendSmsKey(player.tmpBindPhone, player.bindPhoneKey);
    LOG.info("玩家[{}][{}]获取绑定手机验证码[{}]", player.getUserName(), player.getId(), player.bindPhoneKey);

    return ResMessage.DEFAULT;
  }

  /**
   * 绑定手机 .
   * 
   * @param player 玩家.
   * @param key .
   */
  public ResMessage bindPhone(Player player, String key) {
    HuohuaAssert.isTrue(EmptyUtil.stringIsNotEmpty(key));
    // if (key == null) {
    // LOG.error("玩家[{}][{}]绑定手机时未输入验证码", player.getPlayerName(), player.getId());
    // return;
    // }

    HuohuaAssert.isTrue(key.equalsIgnoreCase(player.bindPhoneKey), ErrorCode.SMS_FAIL);
    // if (!key.equalsIgnoreCase(player.bindPhoneKey)) {
    // LOG.warn("玩家[{}][{}]绑定手机时输入验证码不正确", player.getPlayerName(), player.getId());
    // commonMsgMgr.sendErrorDlgMsg(player, ErrorCode.SMS_FAIL, Operator.SYSTEM);
    // return;
    // }

    // 玩家已经绑定手机不能重复绑定;
    HuohuaAssert.isTrue(EmptyUtil.stringIsEmpty(player.getPhone()));
    // if (player.getPhone() != null && !player.getPhone().trim().equals("")) {
    // LOG.error("玩家[{}][{}]已经绑定手机不能重复绑定手机", player.getPlayerName(), player.getId());
    // return;
    // }

    player.setPhone(player.tmpBindPhone);
    player.setValidatePhone(true);

    player.tmpBindPhone = null;
    player.bindPhoneKey = null;
    playerMgr.asyncUpdatePlayer(player);
    LOG.info("玩家[{}][{}]绑定手机成功", player.getUserName(), player.getId());
    // 网页需要立马看到绑定手机信息，立即入库
    playerMgr.asyncUpdatePlayer(player);
    DbLogService.log(new BindPhoneLog(player, 1));

    return msgMgr.resBindPhoneMsg(player.getPhone());
  }

  /**
   * 绑定邮箱 .
   * 
   * @param player 玩家.
   * @param email .
   */
  public ResMessage bindEmail(Player player, String email) {
    HuohuaAssert.isTrue(email.matches(EMAIL_REGEX));
    // if (!email.matches(EMAIL_REGEX)) {
    // commonMsgMgr.sendErrorDlgMsg(player, ErrorCode.BAD_REQUEST, Operator.SYSTEM);
    // LOG.warn("玩家[{}][{}]绑定邮箱时格式不正确", player.getPlayerName(), player.getId(), email);
    //
    // }

    player.setEmail(email);
    player.setValidateEmail(true);
    playerMgr.asyncUpdatePlayer(player);
    return msgMgr.sendBindEmailMsg(email);
  }

  /**
   * 获取解除绑定手机号码验证码 .
   * 
   * @param player 玩家.
   */
  public void getUnBindPhoneKey(Player player) {
    if (player.getPhone() == null) {
      LOG.error("玩家[{}][{}]还没有绑定手机不能解除绑定", player.getPlayerName(), player.getId());
      return;
    }

    long now = System.currentTimeMillis();
    // 给客户端延时2秒
    if (now - player.getUnBindPhoneKeyTime + 2000 < REFRESH_BIND_PHONE_KEY_INTERVAL) {
      LOG.warn("玩家[{}][{}]刷新绑定手机验证码低于时间间隔[{}]毫秒", player.getId(), player.getPlayerName(),
          REFRESH_BIND_PHONE_KEY_INTERVAL);
      msgMgr.sendGetUnBindPhoneKeyMsg(player, 1,
          (int) ((now - player.getUnBindPhoneKeyTime) / 1000));
      return;
    }

    player.unBindPhoneKey = RandomKeyGenerator.generateNum(6);
    player.getUnBindPhoneKeyTime = System.currentTimeMillis();
    msgMgr.sendGetUnBindPhoneKeyMsg(player, 0, 0);
    smsMgr.sendSmsKey(player.getPhone(), player.unBindPhoneKey);
    LOG.info("玩家[{}][{}]获取解除绑定手机号码验证码成功", player.getUserName(), player.getId());
  }

  /**
   * 解除绑定手机 .
   * 
   * @param player 玩家.
   * @param key .
   */
  public void unBindPhone(Player player, String key) {
    if (key == null) {
      LOG.error("玩家[{}][{}]解除手机验证,没有输入验证码", player.getPlayerName(), player.getId());
      return;
    }

    if (!player.unBindPhoneKey.equalsIgnoreCase(key)) {
      LOG.warn("玩家[{}][{}]解除绑定手机时输入验证码不正确", player.getPlayerName(), player.getId());
      commonMsgMgr.sendErrorDlgMsg(player, ErrorCode.SMS_FAIL, Operator.SYSTEM);
      return;
    }

    player.unBindPhoneKey = null;
    player.getUnBindPhoneKeyTime = 0;
    player.setPhone(null);
    player.setValidatePhone(false);

    msgMgr.sendUnBindPhoneMsg(player);
    playerMgr.asyncUpdatePlayer(player);
    LOG.info("玩家[{}][{}]解除绑定手机成功", player.getUserName(), player.getId());
    DbLogService.log(new BindPhoneLog(player, 0));
  }

  /**
   * 修改游戏设置 .
   * 
   * @param player 玩家.
   * @param loginPhoneVerify . 登录手机验证
   * @param playItemEffect . 播放道具特效
   */
  public void modifyGameSetting(Player player, boolean loginPhoneVerify, boolean playItemEffect) {
    player.setLoginPhoneVerify(loginPhoneVerify);
    player.setPlayItemEffect(playItemEffect);

    msgMgr.sendModifyGameSettingMsg(player);
    playerMgr.asyncUpdatePlayer(player);
    LOG.info("玩家[{}][{}]修改游戏设置成功", player.getUserName(), player.getId());
  }

}
